/*
 * Common usable utilities
 *
 * Copyright (c) 2007
 *   Petr Hadraba <hadrabap@bluetone.cz>
 *
 * Author: Petr Hadraba
 *
 * --
 *
 * XML Utilities
 */

package global.sandbox.xmlutilities;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;

/**
 * Simple implementation of the NamespaceContext.
 *
 * @author Petr Hadraba
 * 
 * @version 1.1
 */
public class NamespaceContextImpl implements NamespaceContext {
    
    /** stores namespace mappings */
    private final Map<String, String> namespaces;
    
    /**
     * Creates a new instance of NamespaceContextImpl and adds default
     * namespace URIs
     */
    public NamespaceContextImpl() {
        namespaces = new HashMap<String, String>(4);
        
        addDefaultNamespaces();
    }
    
    /**
     * adds namespace URI specified with prefix and URI
     *
     * @param prefix        prefix of the namespace
     * @param namespaceURI  URI of the namespace
     */
    public void addNamespace(String prefix, String namespaceURI) {
        namespaces.put(prefix, namespaceURI);
    }
    
    /**
     * adds all the namespace URIs that are stored in the specified Map
     *
     * @param namespaceURIs  URIs to add, key is prefix, value is URI
     */
    public void addNamespaces(Map<String, String> namespaceURIs) {
        namespaces.putAll(namespaceURIs);
    }
    
    /**
     * adds default namespace URIs
     *
     * Default namespace URIs are DEFAULT_NS_PREFIX, XML_NS_PREFIX and
     * XMLNS_ATTRIBUTE.
     */
    public void addDefaultNamespaces() {
        namespaces.put(XMLConstants.DEFAULT_NS_PREFIX, XMLConstants.NULL_NS_URI);
        namespaces.put(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
        namespaces.put(XMLConstants.XMLNS_ATTRIBUTE, XMLConstants.XMLNS_ATTRIBUTE_NS_URI);
    }
    
    /**
     * removes specified namespace using prefix
     *
     * @param prefix of the namespace
     */
    public void removeNamespaceByPrefix(String prefix) {
        namespaces.remove(prefix);
    }
    
    /**
     * removes specified namespace using URI
     *
     * @param uri  URI of the namespace to remove
     */
    public void removeNamespaceByURI(String uri) {
        final Iterator it = namespaces.keySet().iterator();
        
        while (it.hasNext()) {
            if (((String) it.next()).equals(uri)) {
                it.remove();
            }
        }
    }
    
    /**
     * removes all the namespace URIs incl. default ones
     */
    public void removeAllNamespaces() {
        namespaces.clear();
    }
    
    /**
     * returnes namespace URI that corresponds to the specified prefix
     *
     * @param prefix  URI of the namespace to obtain
     *
     * @return URI of the namespace or NULL_NS_URI if not found
     */
    public String getNamespaceURI(String prefix) {
        if (prefix == null) {
            throw new IllegalArgumentException(getClass().getPackage().getName()
                    + "." + getClass().getName() + ".getNamespaceURI(null)");
        }
        
        final String uri = namespaces.get(prefix);
        
        if (uri == null) {
            return XMLConstants.NULL_NS_URI;
        }
        
        return uri;
    }
    
    /**
     * returnes the prefix for the corresponding namespace URI
     *
     * this method returnes the first occurrence of the prefix for given URI
     *
     * @param namespaceURI  namespace URI
     *
     * @return prefix for the URI or null if not found
     */
    public String getPrefix(String namespaceURI) {
        if (namespaceURI == null) {
            throw new IllegalArgumentException(getClass().getPackage().getName()
                    + "." + getClass().getName() + ".getPrefix(null)");
        }
        
        final Iterator it = namespaces.keySet().iterator();
        
        while (it.hasNext()) {
            final String prefix = (String) it.next();
            final String uri = namespaces.get(prefix);
            
            if (uri.equals(namespaceURI)) {
                return prefix;
            }
        }
        
        return null;
    }
    
    /**
     * returnes iterator for the set of all the prefixes that correspond to the
     * specified URI
     *
     * @param namespaceURI  namespace URI
     *
     * @return set of prefixes (iterator) or empty set
     */
    public Iterator getPrefixes(String namespaceURI) {
        if (namespaceURI == null) {
            throw new IllegalArgumentException(getClass().getPackage().getName()
                    + "." + getClass().getName() + ".getPrefixes(null)");
        }
        
        ArrayList<String> prefixes = new ArrayList<String>();
        
        final Iterator it = namespaces.keySet().iterator();
        
        while (it.hasNext()) {
            final String prefix = (String) it.next();
            final String uri = namespaces.get(prefix);
            
            if (uri.equals(namespaceURI)) {
                prefixes.add(prefix);
            }
        }
        
        return prefixes.iterator();
    }
    
}
